﻿using System;
using System.ComponentModel;
using EnvDTE;
using VsxFactory.Modeling.VisualStudio;
using Microsoft.VisualStudio;
using Microsoft.VisualStudio.Modeling.Shell;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;
using VsxFactory.Modeling.Strategies;

namespace VsxFactory.Modeling.StrategyManager
{  
    /// <summary>
    /// Classe de base pour les providers d'extenders
    /// </summary>
    public abstract class StrategyExtenderProvider : EnvDTE.IExtenderProvider
    {
        private bool inCanExtend;

        public IServiceProvider ServiceProvider { get; private set; }

        public StrategyExtenderProvider(IServiceProvider serviceProvider)
        {
            System.Diagnostics.Contracts.Contract.Requires(serviceProvider != null);
            this.ServiceProvider = serviceProvider;
        }

        public abstract string Name { get; }

        public bool CanExtend(string extenderCATID, string extenderName, object extendeeObject)
        {
            PropertyDescriptor descriptor = TypeDescriptor.GetProperties(extendeeObject)["ExtenderCATID"];
            if (inCanExtend || descriptor == null)
            {
                return false;
            }

            inCanExtend = true;
            bool flag = ((extenderName.Equals(this.Name) &&
                this.IsSupportedCATID(extenderCATID)) && (descriptor != null)) &&
                this.IsSupportedCATID(descriptor.GetValue(extendeeObject).ToString());
            if (flag)
            {
                string fullPath = TypeDescriptor.GetProperties(extendeeObject)["FullPath"].GetValue(extendeeObject) as string;
                flag = CanExtendFile(fullPath);
            }

            inCanExtend = false;
            return flag;
        }

        /// <summary>
        /// Méthode à implémenter pour valider si le noeud correspondand au fichier à un extender
        /// </summary>
        /// <param name="fullPath"></param>
        /// <returns></returns>
        protected abstract bool CanExtendFile(string fullPath);

        /// <summary>
        /// Création de l'extender correspond au noeud
        /// </summary>
        /// <param name="node">Noeud à étendre</param>
        /// <returns></returns>
        protected abstract IStrategyExtender CreateExtender(IVsProjectFileItem node);

 
        private bool IsSupportedCATID(string ExtenderCATID)
        {
            if (!ExtenderCATID.Equals("{8D58E6AF-ED4E-48B0-8C7B-C74EF0735451}", StringComparison.OrdinalIgnoreCase))
            {
                return ExtenderCATID.Equals("{EA5BD05D-3C72-40A5-95A0-28A2773311CA}", StringComparison.OrdinalIgnoreCase);
            }
            return true;
        }

        public object GetExtender(string ExtenderCATID, string ExtenderName, object ExtendeeObject, EnvDTE.IExtenderSite ExtenderSite, int Cookie)
        {
            IStrategyExtender extender = null;
            try
            {
                if (this.CanExtend(ExtenderCATID, ExtenderName, ExtendeeObject))
                {
                    IVsBrowseObject obj2 = ExtendeeObject as IVsBrowseObject;
                    if (obj2 != null)
                    {
                        IVsHierarchy hierarchy;
                        uint num;
                        obj2.GetProjectItem(out hierarchy, out num);
                        object obj;
                        if (hierarchy.GetProperty(num, (int)__VSHPROPID.VSHPROPID_ExtObject, out obj) == 0)
                        {
                            ProjectItem pi = obj as ProjectItem;
                            if (pi != null)
                            {
                                IStrategyManager sm = ServiceProvider.GetService(typeof(SStrategyManager)) as IStrategyManager;
                                var n = sm.SolutionExplorer.CurrentSolution.FindByPath<IVsProjectFileItem>(pi.FileNames[0]);
                                if (n != null)
                                {
                                    extender = CreateExtender(n);
                                    extender.Init(ExtenderSite, Cookie);
                                }
                            }
                        }
                    }
                }
            }
            catch (Exception )
            {
                // TODO log
            }
            return extender;
        }
    }

}
